#ifndef SIMD___SCALAR_H
#define SIMD___SCALAR_H

#include <math.h>
#include <stdlib.h>//size_t for MSVC 6.0
#include <cstdlib>
#include <cfloat>
#include <float.h>

/* SVN $Revision$ on $Date$ from http://bullet.googlecode.com*/
#define BT_BULLET_VERSION 275

inline int btGetVersion()
{
	return BT_BULLET_VERSION;
}

#if defined(DEBUG) || defined(_DEBUG)
#define BT_DEBUG
#endif

#ifdef WIN32
	#if defined(__MINGW32__) || defined(__CYGWIN__) || (defined (_MSC_VER) && _MSC_VER < 1300)
		
		#define SIMD_FORCE_INLINE inline
		#define ATTRIBUTE_ALIGNED16(a) a
		#define ATTRIBUTE_ALIGNED128(a) a
	#else
		//#define BT_HAS_ALIGNED_ALLOCATOR
		#pragma warning(disable : 4324) // disable padding warning
		//			#pragma warning(disable:4530) // Disable the exception disable but used in MSCV Stl warning.
		//			#pragma warning(disable:4996) //Turn off warnings about deprecated C routines
		//			#pragma warning(disable:4786) // Disable the "debug name too long" warning
		
		#define SIMD_FORCE_INLINE __forceinline
		#define ATTRIBUTE_ALIGNED16(a) __declspec(align(16)) a
		#define ATTRIBUTE_ALIGNED128(a) __declspec(align(128)) a
	#ifdef XBOX
		#define BT_USE_VMX128

		#include <ppcintrinsics.h>
 		#define BT_HAVE_NATIVE_FSEL
		#define btFsel(a,b,c) __fsel((a),(b),(c))
	#else

#if (defined (WIN32) && (_MSC_VER) && _MSC_VER >= 1400) && (!defined (BT_USE_DOUBLE_PRECISION))
			#define BT_USE_SSE
			#include <emmintrin.h>
#endif

	#endif // _XBOX
	#endif // __MINGW32__
	
	#include <assert.h>
#ifdef BT_DEBUG
		#define btAssert assert
#else
		#define btAssert(x)
#endif
	
	//btFullAssert is optional, slows down a lot
	#define btFullAssert(x)

	#define btLikely(_c)  _c
	#define btUnlikely(_c) _c

#else
#if defined	(__CELLOS_LV2__)
		#define SIMD_FORCE_INLINE inline
		#define ATTRIBUTE_ALIGNED16(a) a __attribute__ ((aligned (16)))
		#define ATTRIBUTE_ALIGNED128(a) a __attribute__ ((aligned (128)))
		#ifndef assert
		#include <assert.h>
		#endif
#ifdef BT_DEBUG
		#define btAssert assert
#else
		#define btAssert(x)
#endif
		//btFullAssert is optional, slows down a lot
		#define btFullAssert(x)

		#define btLikely(_c)  _c
		#define btUnlikely(_c) _c

#else

#ifdef USE_LIBSPE2

		#define SIMD_FORCE_INLINE __inline
		#define ATTRIBUTE_ALIGNED16(a) a __attribute__ ((aligned (16)))
		#define ATTRIBUTE_ALIGNED128(a) a __attribute__ ((aligned (128)))
		#ifndef assert
		#include <assert.h>
		#endif
#ifdef BT_DEBUG
		#define btAssert assert
#else
		#define btAssert(x)
#endif
		//btFullAssert is optional, slows down a lot
		#define btFullAssert(x)


		#define btLikely(_c)   __builtin_expect((_c), 1)
		#define btUnlikely(_c) __builtin_expect((_c), 0)
		

#else
	//non-windows systems

#if (defined (__APPLE__) && defined (__i386__))
	#define BT_USE_SSE
	#include <emmintrin.h>

	#define SIMD_FORCE_INLINE inline
///@todo: check out alignment methods for other platforms/compilers
	#define ATTRIBUTE_ALIGNED16(a) a __attribute__ ((aligned (16)))
	#define ATTRIBUTE_ALIGNED128(a) a __attribute__ ((aligned (128)))
	#ifndef assert
	#include <assert.h>
	#endif

	#if defined(DEBUG) || defined (_DEBUG)
		#define btAssert assert
	#else
		#define btAssert(x)
	#endif

	//btFullAssert is optional, slows down a lot
	#define btFullAssert(x)
	#define btLikely(_c)  _c
	#define btUnlikely(_c) _c

#else

		#define SIMD_FORCE_INLINE inline
		///@todo: check out alignment methods for other platforms/compilers
		///#define ATTRIBUTE_ALIGNED16(a) a __attribute__ ((aligned (16)))
		///#define ATTRIBUTE_ALIGNED128(a) a __attribute__ ((aligned (128)))
		#define ATTRIBUTE_ALIGNED16(a) a
		#define ATTRIBUTE_ALIGNED128(a) a
		#ifndef assert
		#include <assert.h>
		#endif

#if defined(DEBUG) || defined (_DEBUG)
		#define btAssert assert
#else
		#define btAssert(x)
#endif

		//btFullAssert is optional, slows down a lot
		#define btFullAssert(x)
		#define btLikely(_c)  _c
		#define btUnlikely(_c) _c
#endif //__APPLE__ 

#endif // LIBSPE2

#endif	//__CELLOS_LV2__
#endif

///The btScalar type abstracts floating point numbers, to easily switch between double and single floating point precision.
#if defined(BT_USE_DOUBLE_PRECISION)
typedef double btScalar;
//this number could be bigger in double precision
#define BT_LARGE_FLOAT 1e30
#else
typedef float btScalar;
//keep BT_LARGE_FLOAT*BT_LARGE_FLOAT < FLT_MAX
#define BT_LARGE_FLOAT 1e18f
#endif

#define BT_DECLARE_ALIGNED_ALLOCATOR() \
	SIMD_FORCE_INLINE void* operator new(size_t sizeInBytes) {return btAlignedAlloc(sizeInBytes,16);} \
	SIMD_FORCE_INLINE void operator delete(void* ptr) {btAlignedFree(ptr);} \
	SIMD_FORCE_INLINE void* operator new(size_t, void* ptr) {return ptr;} \
	SIMD_FORCE_INLINE void  operator delete(void*, void*)      { }   \
	SIMD_FORCE_INLINE void* operator new[](size_t sizeInBytes)   { return btAlignedAlloc(sizeInBytes,16); }   \
	SIMD_FORCE_INLINE void  operator delete[](void* ptr)         { btAlignedFree(ptr); }   \
	SIMD_FORCE_INLINE void* operator new[](size_t, void* ptr)   { return ptr; }   \
    SIMD_FORCE_INLINE void  operator delete[](void*, void*)      { }   \

#if defined(BT_USE_DOUBLE_PRECISION) || defined(BT_FORCE_DOUBLE_FUNCTIONS)
		
SIMD_FORCE_INLINE btScalar btSqrt(btScalar x) { return sqrt(x); }
SIMD_FORCE_INLINE btScalar btFabs(btScalar x) { return fabs(x); }
SIMD_FORCE_INLINE btScalar btCos(btScalar x) { return cos(x); }
SIMD_FORCE_INLINE btScalar btSin(btScalar x) { return sin(x); }
SIMD_FORCE_INLINE btScalar btTan(btScalar x) { return tan(x); }
SIMD_FORCE_INLINE btScalar btAcos(btScalar x) { return acos(x); }
SIMD_FORCE_INLINE btScalar btAsin(btScalar x) { return asin(x); }
SIMD_FORCE_INLINE btScalar btAtan(btScalar x) { return atan(x); }
SIMD_FORCE_INLINE btScalar btAtan2(btScalar x, btScalar y) { return atan2(x, y); }
SIMD_FORCE_INLINE btScalar btExp(btScalar x) { return exp(x); }
SIMD_FORCE_INLINE btScalar btLog(btScalar x) { return log(x); }
SIMD_FORCE_INLINE btScalar btPow(btScalar x,btScalar y) { return pow(x,y); }
SIMD_FORCE_INLINE btScalar btFmod(btScalar x,btScalar y) { return fmod(x,y); }

#else



#endif

